package com.strongbj.iot.devices.hr.response.handle;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.strongbj.core.message.IMessageHandle;
import com.strongbj.core.tag.DefualtTagRule;
import com.strongbj.core.tag.ITagRule;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.core.util.ContextUtils;
import com.strongbj.iot.devices.hr.message.HRMessage;
import com.strongbj.iot.devices.hr.message.MQMessageOfHR;
import com.strongbj.iot.devices.hr.response.entity.ScanLabInfoOfDoor;
import com.strongbj.iot.mq.producer.TopicSender;

import io.netty.channel.ChannelHandlerContext;

public class HRReadLabelsInTriggerModeHandle implements IMessageHandle<HRMessage, Object> {
	protected static Logger logger = LogManager.getLogger(HRReadLabelInTriggerModeHandle.class.getName());
	protected TopicSender topicSender = (TopicSender) ContextUtils.getBean("topicSender");
	protected static final String ACTION_CODE = "collect020";
	private Map<String, List<String>> labs = new HashMap<>(); // 存取在结束扫描前保存的标签数组

	public Map<String, String> doorDirectionMap = new HashMap<>(); // 见目录“/DAIOServer/src/main/resources/project/jd/properties/hr.properties”，hr.properties
																	// 中配置了门禁安装时的方向，格式是“IP,为进入方向所属的红外线（数字）”，比如，认为触发了红外1号端口时，就是进入，则
																	// 写成"IP,1",反之，认为触发了红外2号端口就是进入的话，就配成“IP,2"。具体配置视安装情况。多个门禁用“;”隔开。

	public Map<String, String> doorRealityDirectionMap = new HashMap<>(); // key是门禁IP，value是现在触碰的红外端口。每次触碰该门禁的红外端口时，value值会相应改变。

	public ITagRule tagRule = new DefualtTagRule();

//private HashedWheelTimer hashedWheelTimer = new HashedWheelTimer();

	public HRReadLabelsInTriggerModeHandle(String doorDirection) {
		try {
			String[] doorD = doorDirection.split(";");
			for (String s : doorD) {
				if (!"".equals(s) && s != null) {
//			System.out.println(s);   // 打印连接的门禁
					String[] d = s.split(",");
					doorDirectionMap.put(d[0], d[1]); // IP为key,方向为值。
				}
			}
		} catch (Exception e) {
			logger.error(
					"/DAIOServer/src/main/resources/project/jd/properties/hr.properties  文件 中 “hr.server.doorDirection”项配置有误");
			e.printStackTrace();
		}
	}

	@Override
	public boolean isHandle(HRMessage t) {
		if (t.getCommand() == 0x39) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Object handle(ChannelHandlerContext ctx, HRMessage t) {
		if (t.getData().length > 3) {
			// 数据长度大于3位即读取标签数据
			int validDataLen = t.getData()[0]; // 有效数据长度
			byte rSSI = t.getData()[1]; // RSSI值
			byte antennaNum = t.getData()[validDataLen]; // 读取天线号
			String labCode = ByteUtil.byteArrToHexString(t.getData(), 2, validDataLen - 2); // 标签编号
			if (tagRule.isValid(labCode)) {
				this.labHandle(ctx, rSSI, antennaNum, labCode); // 标签处理
			}
		} else if (t.getData().length == 2) {
			// 数据长度等于2表示开始寻卡
			byte triggerInfraredNum = t.getData()[0]; // 触发的红外引脚编号
			this.startAntennaScanHandle(ctx, triggerInfraredNum);
		} else if (t.getData().length == 3) {
			byte antennaNum = t.getData()[2]; // 读取天线号
			if (t.getData()[0] == 0xFF && t.getData()[1] == 0xFF) {
				// 当所有天线工作结束返回结束标记数据 0xFFFF 和结束的天线号
				this.endAllAntennaScanHandle(ctx, antennaNum);
			} else {
				// 当前天线工作结束时主动返回当前天线号和读到的标签记录条数
				int labCount = t.getData()[0] + t.getData()[1] * 256; // 记录条数=
																		// Data[0]+
																		// Data[1]*256
				this.endCurrentAntennaScanHandle(ctx, antennaNum, labCount);
			}
		}
		return null;
	}

	/**
	 * 标签的处理
	 * 
	 * @param ctx
	 * @param rSSI       RSSI值
	 * @param antennaNum 天线号
	 * @param labCode    标签编码
	 */
	protected void labHandle(ChannelHandlerContext ctx, byte rSSI, byte antennaNum, String labCode) {
		logger.info("HR设备[ip:{}] 读取标签，标签号={},		天线号={}		RSSI={}", ctx.channel().remoteAddress().toString(),
				labCode, antennaNum, rSSI);

		List<String> labList = labs.get(ctx.channel().remoteAddress().toString());
		if (labList == null) {
			labList = new ArrayList<>();
			labs.put(ctx.channel().remoteAddress().toString(), labList);
		}
		if (!labList.contains(labCode.substring(labCode.length() - 8)))
			labList.add(labCode.substring(labCode.length() - 8));

//		MQMessageOfHR msg = new MQMessageOfHR();
//		msg.setActioncode(ACTION_CODE);
//		ScanLabInfoOfDoor slid = new ScanLabInfoOfDoor();
//		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
//		slid.setDevIp(insocket.getAddress().getHostAddress());
//		slid.setDirection(getRealDirection(slid.getDevIp())); // 获取该门禁此时实际的方向
//		List<String> list = new ArrayList<String>();
//		list.add(labCode.substring(labCode.length() - 8));
//		slid.setRfids(list);
//		msg.setAwsPostdata(slid);
//		String json = JSON.toJSONString(msg);
//		logger.info("HR设备 向MQ发送标签数据（后8位上传）	 JSON={}", json);
//		topicSender.send("hrReader", json);

//BuzzerEntity be = new BuzzerEntity();
//be.setAlarmTime(6000);
//byte[] data = messageDataToBytes(be);
//System.out.println("============================");
//System.out.println(ByteUtil.byteArrToHexString(data));
//ByteBuf bs  = Unpooled.copiedBuffer(data);
//ctx.channel().writeAndFlush(bs);
//
//hashedWheelTimer.newTimeout(new TimerTask() {
//    @Override
//    public void run(Timeout timeout) throws Exception {
//    		ByteBuf bs  = Unpooled.copiedBuffer(new byte[] {0x1B,0x01,0x00,0x00,0x00,0x00,0x00});
//			ctx.channel().writeAndFlush(bs);
//			System.out.println("打印了切换模式的");
//    }
//}, 5000, TimeUnit.MILLISECONDS);
//

	}

//private byte[] messageDataToBytes(BuzzerEntity buzzer){
//HRMessageFactory hrFactory=new HRMessageFactory();
//// 计算重复次数（假定响1秒，停1秒）
//long repetitions = buzzer.getAlarmTime()/2000;
//byte[] datas = new byte[]{0xA,0xA,0x0};
//// 设置重复次数，如果重复次数超过255，就按255次执行
//datas[2]=(byte)Math.min((int)repetitions,255);
//// 获取二进制的消息
//return hrFactory.createHRMessage((byte)0x0F, (byte)0x0, (byte)0x0, datas);
//}
	/**
	 * 获取该门禁此时实际的方向
	 * 
	 * @param devIp
	 * @return
	 */
	protected String getRealDirection(String devIp) {
		String realDirection = null;
		if (doorRealityDirectionMap.get(devIp) != null && doorDirectionMap.get(devIp) != null) {
			String nowTriggeredPort = doorRealityDirectionMap.get(devIp); // 现在触发的端口
			String configureEnterDirection = doorDirectionMap.get(devIp); // 配置文件中，配置该门禁方向为”进入“的红外线端口。
			if (nowTriggeredPort.equals(configureEnterDirection)) { // 如果现在触发的端口和配置的端口相同，表示进入，反之为出。
				realDirection = "I";
			} else {
				realDirection = "E";
			}
		}
		return realDirection;
	}

	/**
	 * 开始寻卡的处理
	 * 
	 * @param ctx
	 * @param triggerInfraredNum 触发的红外编号
	 */
	protected void startAntennaScanHandle(ChannelHandlerContext ctx, byte triggerInfraredNum) {
		logger.info("HR设备[ip:{}] 触发了第{}条红外", ctx.channel().remoteAddress(), triggerInfraredNum);
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
		saveNowDirection(insocket.getAddress().getHostAddress(), String.valueOf(triggerInfraredNum)); // 保存该门禁现在的方向。注：京东的门禁，和厂家了解过，它只支持单向触发。比如我触发红外1号端口后，在一定时间范围内，再去触发红外2号端口，门禁是会忽略触发2号端口的信号的。所以【不会】出现
																										// 方向刚被改成1（进）时，再传递标签给业务系统时，去doorRealityDirectionMap中取方向时，方向已经被改成了2（出）
		labs.put(ctx.channel().remoteAddress().toString(), new ArrayList<>());
	}

	/**
	 * 保存该门禁现在的方向
	 * 
	 * @param remoteAddress
	 * @param triggerInfraredNum
	 */
	protected void saveNowDirection(String remoteAddress, String triggerInfraredNum) {
		doorRealityDirectionMap.put(remoteAddress, triggerInfraredNum);
	}

	/**
	 * 结束所有天线的寻卡处理
	 * 
	 * @param ctx
	 * @param antennaNum 天线编号
	 */
	protected void endAllAntennaScanHandle(ChannelHandlerContext ctx, byte antennaNum) {
		this.sendData(ctx);
		logger.info("所有天线工作已结束，天线号={}", antennaNum);
	}

	/**
	 * 结束当前天线的寻卡处理
	 * 
	 * @param ctx
	 * @param antennaNum 天线编号
	 * @param labCount   扫到的标签数量
	 */
	protected void endCurrentAntennaScanHandle(ChannelHandlerContext ctx, byte antennaNum, int labCount) {
		logger.info("当前天线工作已结束，天线号={},	标签记录条数={}", antennaNum, labCount);
	}

	protected void sendData(ChannelHandlerContext ctx) {
		List<String> labList = labs.get(ctx.channel().remoteAddress().toString());
		MQMessageOfHR msg = new MQMessageOfHR();
		msg.setActioncode(ACTION_CODE);
		ScanLabInfoOfDoor slid = new ScanLabInfoOfDoor();
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
		slid.setDevIp(insocket.getAddress().getHostAddress());
		slid.setDirection(getRealDirection(slid.getDevIp())); // 获取该门禁此时实际的方向
		slid.setRfids(labList);
		msg.setAwsPostdata(slid);
		String json = JSON.toJSONString(msg);
		logger.info("HR设备 向MQ发送标签数据（后8位上传）	 JSON={}", json);
		topicSender.send("hrReader", json);
	}
}
